from hashlib import sha1
from Alibb.settings import settings
from hmac import new
from time import time_ns


class BaseApi:

    def __init__(self, access_token, client, api_key, timestamp, api_url):
        self._request_url = 'https://gw.open.1688.com/openapi/'  # 最终请求路径
        self._access_token = access_token  # 用户授权令牌
        self._session = client  # aiohttp实例
        self._api_url = api_url  # api_url / urlPath
        self._api_key = api_key
        self._timestamp = timestamp
        self._req_url = self._request_url + self._api_url + "/" + self._api_key

    def _get_sign(self, param_):

        temp_list = []

        if self._timestamp:
            param_['_aop_timestamp'] = str(time_ns())[:-6]

        param_['access_token'] = self._access_token

        # 拼装签名串
        for k, v in param_.items():
            temp_list.append(k + str(v))

        temp_list.sort()

        urlpath = self._api_url + "/" + self._api_key
        param_str = "".join(temp_list)

        # 拼接字符串
        s = urlpath + param_str

        # 生成sign
        s = bytes(s.encode('utf-8'))
        sha = new(bytes(settings['app_secret'].encode('utf-8')), None, sha1)
        sha.update(s)

        param_['_aop_signature'] = sha.hexdigest().upper()

        return param_

    @staticmethod
    def _get_body(param):

        body = ""

        length = len(param)

        for num, tuple_temp in enumerate(param.items()):
            if num == length - 1:
                body += f"{tuple_temp[0]}={str(tuple_temp[1])}"
                break
            body += f"{tuple_temp[0]}={str(tuple_temp[1])}&"

        return body

    async def post(self, param):

        # 进行签名
        param = self._get_sign(param)

        body = self._get_body(param)

        # 开始请求
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Host": "gw.open.1688.com",
            "Connection": "Keep-Alive",
            "Accept-Encoding": "gzip,deflate"
        }

        async with self._session.post(self._req_url, timeout=5, data=body, headers=headers) as resp:
            status_code = resp.status
            text = await resp.text()

        return status_code, text
